﻿///***************************************************************
/// 시  스  템 : SMFramework
/// 단위시스템 : Utility
/// 계      층 : Framework Utility
/// 프로그램명 : DateUtil
/// 파  일  명 : DateUtil.cs
/// 설      명 : 날짜관련 유틸리티
///***************************************************************
/// 수정ID 일자       이름     내용
///---------------------------------------------------------------
/// CH001  2008-07-02 송시명   최초 작성
///***************************************************************
///
using System;
using System.Globalization;
using SMFramework.Configuration;

namespace SMFramework.Utility
{
	/// <summary>
	/// 날짜관련 유틸리티
	/// </summary>
    public sealed class DateUtil
	{
		private DateUtil()
		{
		}

		#region 현재날짜변환

		/// <summary>
		/// 현재날짜변환
		/// </summary>
		/// <returns></returns>
		public static string GetNow()
		{
			return GetNow("yyyy-MM-dd");
		}

		/// <summary>
		/// 현재날짜변환
		/// </summary>
		/// <param name="ps_mark"></param>
		/// <returns></returns>
		public static string GetNow(string ps_mark)
		{
            return ValidationUtil.IsDateMask(ps_mark) ? DateTime.Now.ToString(ps_mark) : DateTime.Now.ToString("yyyy-MM-dd");
		}	
		
		#endregion

		#region 현재년/월/일

		/// <summary>
		/// 현재년도를 기준으로 이전,이후 년도 검색 (mask : yyyy-MM-dd)
		/// </summary>
		/// <param name="pi_add_y"></param>
		/// <returns></returns>
		public static string GetYearEx(int pi_add_y)
		{
			return DateTime.Now.AddYears(pi_add_y).ToString("yyyy-MM-dd");
		}
		
		/// <summary>
		/// 현재년도를 기준으로 이전,이후 년도 검색
		/// </summary>
		/// <param name="pi_add_y"></param>
		/// <param name="ps_mark"></param>
		/// <returns></returns>
		public static string GetYearEx(int pi_add_y, string ps_mark)
		{
			return DateTime.Now.AddYears(pi_add_y).ToString(ps_mark);
		}


		/// <summary>
		/// 현재월 리턴
		/// </summary>
		/// <returns></returns>
		public static string GetMonthEx()
		{
			return DateTime.Now.ToString("yyyy-MM").Substring(5);
		}
		
		/// <summary>
		/// 현재월을 기준으로 이전,이후 월 검색 (mask : yyyy-MM-dd)
		/// </summary>
		/// <param name="pi_add_m"></param>
		/// <returns></returns>
		public static string GetMonthEx(int pi_add_m)
		{
			return DateTime.Now.AddMonths(pi_add_m).ToString("yyyy-MM-dd");
		}
		
		/// <summary>
		/// 현재월을 기준으로 이전,이후 월 검색
		/// </summary>
		/// <param name="pi_add_m"></param>
		/// <param name="ps_mark"></param>
		/// <returns></returns>
		public static string GetMonthEx(int pi_add_m, string ps_mark)
		{
			return DateTime.Now.AddMonths(pi_add_m).ToString(ps_mark);
		}

		/// <summary>
		/// 현재일 리턴
		/// </summary>
		/// <returns></returns>
		public static string GetDayEx()
		{
			return DateTime.Now.ToString("yyyy-MM-dd").Substring(8);
		}
		
		/// <summary>
		/// 현재일을 기준으로 이전,이후 날짜 검색 (mask : yyyy-MM-dd)
		/// </summary>
		/// <param name="pi_add_d"></param>
		/// <returns></returns>
		public static string GetDayEx(int pi_add_d)
		{
			return DateTime.Now.AddDays(pi_add_d).ToString("yyyy-MM-dd");
		}

		/// <summary>
		/// 현재일을 기준으로 이전,이후 날짜 검색, 시간은 구하지 않는다.
		/// </summary>
		/// <param name="pi_add_d"></param>
		/// <param name="ps_mark"></param>
		/// <returns></returns>
		public static string GetDayEx(int pi_add_d, string ps_mark)
		{
			return DateTime.Now.AddDays(pi_add_d).ToString(ps_mark);
		}
		
		#endregion

		#region 날짜간 차이

		/// <summary>
		/// 두 년월사이의 년월정보를 리턴. 기본마스크(yyyy-MM). 200611 ~ 200701 이면 2006-11,2006-12,2007-01
		/// </summary>
		/// <param name="ps_from_ym"></param>
		/// <param name="ps_to_ym"></param>
		/// <returns></returns>
		public static string GetDiffMonthList(string ps_from_ym, string ps_to_ym)
		{
			return GetDiffMonthList(ps_from_ym, ps_to_ym, "yyyy-MM");
		}

		/// <summary>
		/// 두 년월사이의 년월정보를 리턴. 사용자가 마스크 지정. 200611 ~ 200701 이면 2006-11,2006-12,2007-01
		/// </summary>
		/// <param name="ps_from_ym"></param>
		/// <param name="ps_to_ym"></param>
		/// <param name="ps_mask"></param>
		/// <returns></returns>
		public static string GetDiffMonthList(string ps_from_ym, string ps_to_ym, string ps_mask)
		{
			int diff = GetDiffMonth(ps_from_ym, ps_to_ym) + 1;	//ps_to_ym포함
			string rslt = string.Empty;

			if (diff > 0)
			{
				for (int i = 0; i < diff; i++)
				{
					rslt += GetCalcMonth(ps_from_ym, i, ps_mask) + ",";
				}
			}
			else
			{
				return GetCalcMonth(ps_from_ym, 0, ps_mask);
			}
			rslt = rslt.Substring(0, rslt.LastIndexOf(","));

			return rslt;
		}

		/// <summary>
		/// 두 년월의 차이개월수를 구한다. 200611 ~ 200703 이면 24087 - 24083 = 4
		/// </summary>
		/// <param name="ps_from_ym"></param>
		/// <param name="ps_to_ym"></param>
		/// <returns></returns>
		public static int GetDiffMonth(string ps_from_ym, string ps_to_ym)
		{
			int li_result;
			string ls_from_year		= (ps_from_ym.Replace("-", "")).Replace("/", "").Substring(0, 4);
			string ls_to_year		= (ps_to_ym.Replace("-", "")).Replace("/", "").Substring(0, 4);
			string ls_from_month	= (ps_from_ym.Replace("-", "")).Replace("/", "").Substring(4, 2);
			string ls_to_month		= (ps_to_ym.Replace("-", "")).Replace("/", "").Substring(4, 2);

			int li_from = Convert.ToInt32(ls_from_year) * 12 + Convert.ToInt32(ls_from_month);
			int li_to = Convert.ToInt32(ls_to_year) * 12 + Convert.ToInt32(ls_to_month);

			li_result = li_to - li_from;

			return li_result;
		}

		/// <summary>
		/// 두 년월일의 차이일수를 구한다.
		/// </summary>
		/// <param name="ps_from_ymd"></param>
		/// <param name="ps_to_ymd"></param>
		/// <returns></returns>
		public static int GetDiffDay(string ps_from_ymd, string ps_to_ymd)
		{
			TimeSpan lo_result;

			DateTime lo_from = Convert.ToDateTime(ps_from_ymd);
			DateTime lo_to = Convert.ToDateTime(ps_to_ymd);

			lo_result = lo_to - lo_from;

			return lo_result.Days;
		}

		/// <summary>
		/// 두 년월일의 차이일수를 구한다. 문자열로 리턴. 앞에+를 붙일지 여부
		/// </summary>
		/// <param name="ps_from_ymd"></param>
		/// <param name="ps_to_ymd"></param>
		/// <param name="pb_mark"></param>
		/// <returns></returns>
		public static string GetDiffDay(string ps_from_ymd, string ps_to_ymd, bool pb_mark)
		{
			string ls_result = "";
			TimeSpan lo_result;

			DateTime lo_from = Convert.ToDateTime(ps_from_ymd);
			DateTime lo_to = Convert.ToDateTime(ps_to_ymd);

			lo_result = lo_to - lo_from;

			if (lo_result.Days > 0)
			{
				ls_result = pb_mark ? "+" + lo_result.Days.ToString() : lo_result.Days.ToString();
			}
			else
			{
				ls_result = lo_result.Days.ToString();
			}

			return ls_result;
		}
		
		#endregion
		
		#region 날짜변환

		/// <summary>
		/// 8자형 날짜데이터(20050725)를 10자형 날짜 데이터(2005-07-25)로 변환. 
		/// </summary>
		/// <param name="ps_data"></param>
		/// <returns></returns>
		public static string FormatDate(string ps_data)
		{
			string ls_result = "";
			if (String.IsNullOrEmpty(ps_data) || !ValidationUtil.IsEightDate(ps_data))
			{
				ls_result = "";
			}

			try
			{
                string ls_temp = ConversionUtil.ExtractNumberStr(ps_data);
				ls_result = ls_temp.Insert(4, "-").Insert(7, "-");

				return ls_result;
			}
			catch
			{
				return ls_result;
			}
		}

		/// <summary>
		/// 한자리수를 두자리수로 변환한다
		/// </summary>
		/// <param name="ps_date"></param>
		/// <returns></returns>
		public static string ConvertMonthFormat(string ps_date)
		{
			string ls_result = "";
			ls_result = (ps_date.Length < 2) ? "0" + ps_date : ps_date;

			return ls_result;
		}

		/// <summary>
		/// 날짜 형식 변환
		/// </summary>
		/// <param name="ps_date"></param>
		/// <param name="ps_mask"></param>
		/// <returns></returns>
		public static string ConvertDateMask(string ps_date, string ps_mask)
		{
			return Convert.ToDateTime(ps_date).ToString(ps_mask);
		}

		/// <summary>
		/// 날짜 형식 변환 - 언어별
		/// </summary>
		/// <param name="ps_date"></param>
		/// <param name="ls_mask"></param>
		/// <param name="ls_lang_set"></param>
		/// <returns></returns>
		public static string ConvertDateMask(string ps_date, string ls_mask, string ls_lang_set)
		{
			string ps_mask = String.Empty;

			if (ls_lang_set == "ko")
			{
				//한글이고
				switch (ls_mask)
				{
					case "yyyyMM":
					case "yyyy-MM":
					case "yyyy MM":
						ps_mask = WebConfig.SMFramework["Date.Format.yyyyMM.Kor"];
						break;
					default:
						ps_mask = ls_mask;
						break;
				}
			}
			else
			{
				//한글이 아니고
				switch (ls_mask)
				{
					case "yyyyMM":
					case "yyyy-MM":
					case "yyyy MM":
						ps_mask = WebConfig.SMFramework["Date.Format.yyyyMM.Eng"];
						break;
					default:
						ps_mask = ls_mask;
						break;
				}
			}

			return Convert.ToDateTime(ps_date).ToString(ps_mask);
		}
		
		#endregion
		
		#region 날짜계산

		/// <summary>
		/// 특정년월로부터 이전월(이후월)을 계산하여 리턴한다. 호출시 데이터의 형식은 'yyyy-MM-dd(또는 yyyyMMdd 또는 yyyy-MM 또는 yyyyMM)'이다.
		/// </summary>
		/// <param name="ps_ymd"></param>
		/// <param name="li_add_month"></param>
		/// <param name="ls_mask"></param>
		/// <returns></returns>
		public static string GetCalcMonth(string ps_ymd, int li_add_month, string ls_mask)
		{
			string ls_result, ls_ymd = String.Empty;

			if (!String.IsNullOrEmpty(ps_ymd))
			{
				//년월일로 넘어오면 2007-01-01
				if (ps_ymd.Length == 10 && ps_ymd.Contains("-"))	// 2007-02-11이면
				{
					ls_ymd = ps_ymd;
				}
				if (ps_ymd.Length == 8 && !ps_ymd.Contains("-"))	// 20070211이면
				{
					ls_ymd = ps_ymd.Insert(4, "-").Insert(7, "-");
				}
				
				// (형변환을 위해) 200702(or 2007-02)를 2007-02-01로 치환.
				if (ps_ymd.Length == 7 && ps_ymd.Contains("-"))	// 2007-02이면
				{
					ls_ymd = ps_ymd + "-01";
				}
				
				if (ps_ymd.Length == 6 && !ps_ymd.Contains("-"))	// 200702이면
				{
					ls_ymd = ps_ymd.Insert(4, "-") + "-01";
				}

				ls_result = Convert.ToDateTime(ls_ymd).AddMonths(li_add_month).ToString(ls_mask);
			}
			else
			{
				ls_result = Convert.ToDateTime(GetNow()).AddMonths(li_add_month).ToString(ls_mask);
			}
			return ls_result;
		}


		/// <summary>
		/// 특정년월일로부터 이전일(이후일)을 계산하여 리턴한다. 호출시 데이터의 형식은 'yyyy-MM-dd'이다.
		/// </summary>
		/// <param name="ls_ymd"></param>
		/// <param name="li_add_days"></param>
		/// <param name="ls_mask"></param>
		/// <returns></returns>
		public static string GetCalcDay(string ls_ymd, int li_add_days, string ls_mask)
		{
			string ls_result = String.Empty;

			if (ValidationUtil.IsDate(ls_ymd))
			{
				ls_result = Convert.ToDateTime(ls_ymd).AddDays(li_add_days).ToString(ls_mask);
			}

			return ls_result;
		}

		/// <summary>
		/// 년월을 계산하여 월의 마지막일을 리턴한다. 호출시 데이터의 형식은 'yyyy-MM(또는 yyyyMM)'이다.
		/// </summary>
		/// <param name="ls_ym"></param>
		/// <returns></returns>
		public static string GetLastDay(string ls_ym)
		{
			string ls_result = String.Empty;
			int li_year, li_month;
			string[] la_month_day = new String[] { "31", "28", "31", "30", "31", "30", "31", "31", "30", "31", "30", "31" };			

			if (ls_ym.Length == 6)
			{
				li_year = Convert.ToInt32(ls_ym.Substring(0, 4));
				li_month = Convert.ToInt32(ls_ym.Substring(4, 2));
			}
			else if (ls_ym.Length == 7)
			{
				li_year = Convert.ToInt32(ls_ym.Substring(0, 4));
				li_month = Convert.ToInt32(ls_ym.Substring(5, 2));
			}
			else
			{
				return "";
			}

			if (li_year < 1900)	{ li_year = 1900; }
			if (li_month > 12 || li_month < 1) { li_month = 1; }

			//윤달처리
			if (li_year % 4 == 0)
			{
				la_month_day[1] = "29";
			}

			ls_result = la_month_day[li_month - 1].ToString();

			return ls_result;
		}

		/// <summary>
		/// 년월을 계산하여 월의 마지막일을 리턴(년월일)한다. 호출시 데이터의 형식은 'yyyy-MM(또는 yyyyMM)'이다.
		/// </summary>
		/// <param name="ls_ym"></param>
		/// <returns></returns>
		public static string GetLastMonthDay(string ls_ym)
		{
			string ls_result = String.Empty;
			string ls_ymd = "";
			string ls_last_day = GetLastDay(ls_ym);

			if (ls_ym.Length == 6)
			{
				ls_ymd = ls_ym + ls_last_day;
			}
			else if (ls_ym.Length == 7)
			{
				ls_ymd = ls_ym + "-" + ls_last_day;
			}

			ls_result = Convert.ToDateTime(ls_ymd).ToString("yyyy-MM-dd");

			return ls_result;
		}

		#endregion

		#region 시간관련

		/// <summary>
		/// 시간을 계산하여 두자리 시간으로 변경
		/// </summary>
		/// <param name="hh"></param>
		/// <param name="add"></param>
		/// <param name="mm"></param>
		/// <returns></returns>
		public static string ConvertHourFormat(string hh, int add, string mm)
		{
			int tmp = 0;
			int final = 0;

			string tmp_hh = "";
			string tmp_mm = "";

			if (hh != "--")
			{
				tmp = Convert.ToInt32(hh);
				final = (tmp + add);	//21 + 9;

				final = (final > 24) ? final - 24 : final;

				tmp_hh = (final < 10) ? "0" + final.ToString() : final.ToString();
			}

			if (mm != "--")
			{
				tmp_mm = ":" + mm;
			}

			return tmp_hh + tmp_mm;
		}

		#endregion
	}
}
